<!-- @format -->

<template>
	<div class="draw">
		<div class="">下面是画板</div>
        <input type="text" style="width: 500px;" v-model="baseUrl" placeholder="websocket地址" />
        
        <div style="display:flex">
            <input type="text" v-model="value" placeholder="连接websocket的ID" />
            <div @click="startConnect()">点击开始连接--</div>
            <div @click="stopConnect()">点击断开连接--</div>
            <div @click="clear()">点击清空画板</div>
        </div>
        <div class="" style="width: 500px;height: 500px;overflow: hidden;">
            <canvas id="canvas" width="500px" height="500px" style="width: 500px;height: 500px;overflow: hidden;"></canvas>
        </div>
        <br />
        <input type="text" v-model="chatVal" placeholder="发送单条消息"  @keyup.enter.native="chatSend()" />
        <span @click="chatSend()">发送</span>
        <div class="">接收消息</div>
        <div style="border: 1px solid;">
            <div v-for="(item,index) in chatList" :key="index">
                <div>{{item.userId}}:{{item.chatVal}}</div>
            </div>
        </div>
	</div>
</template>

<script>
import { fabric } from "fabric";
export default {
	name: "Draw",
	data() {
        return {
            value: Date.now(),
            canvas: null,
            mouseFrom: {}, //起点的xy坐标
            mouseTo: {}, //终点的xy轴坐标
            currentObjectAid: null, //当前绘制的图形对象
            doDrawing: false, //是否正在绘制
            drawingObject: null, //当前绘制的图形对象
            canvasObjectDefault: {
                fill: 'transparent',
                stroke: 'red',
                strokeWidth: '10',
                strokeLineJoin: 'round',
            },
            baseUrl: "ws://192.168.2.111:8080/room/room_100/",
            // baseUrl: "ws://giroro.tpddns.cn:8081/room/room_100/",

            chatVal: "",
            chatList: [],

        }
	},
    mounted() {
        //检测断网
        window.addEventListener('offline', () => {
            console.log('没有网');
            // this.stopConnect();
            // this.ws.close()
        });
        //检测在线
        window.addEventListener('online', () => {
            console.log('有网');
            this.startConnect();
        });
    },
	methods: {
		startConnect() {
            console.log('加入房间前');
            if (this.ws) {
                this.ws.close();
                this.ws = null;
            }
            this.ws = new WebSocket(this.baseUrl+this.value);
            this.ws.onopen = (event) => {
                console.log('onopen', event, event.target.readyState);
                // 开始绘制画板
                this.startDraw()
            };
            this.ws.onmessage = (event) => {
                if (!event.data || event.data.indexOf("pong") !== -1) return
                let msg = JSON.parse(event.data);
                console.log('接收消息0', msg);
                if (msg.event == 'msg' &&  msg.data != '') {
                    if (msg.userId != this.value) {
                        let data = JSON.parse(msg.data).event;
                        console.log('接收消息1', data);
                        if (data.type == "line"){
                            this.drawing(data.canvasObject)
                        }else if (data.type == "canvasMove") {
                            this.setCanvasObject(data.canvasObject)
                        }
                    }
                    
                    let data = JSON.parse(msg.data).event;
                    if (data.type == "msg") {
                        this.chatList.push(data)
                    }
                }
            };
            this.ws.onerror = (event) => {
                console.error('onerror', event);
            };
            this.ws.onclose = (event) => {
                console.error('onclose', event,navigator.onLine);
            };
        },
		stopConnect() {
            console.log('离开房间', this.ws);
            if (this.ws) {
                this.ws.close();
                this.ws = null;
                this.doDrawing = false; //是否是绘制状态
                this.canvas.isDrawingMode = false;
            }
        },
        // 发送消息
        send(type, data, to) {
            console.log('发送消息', type, data, to);
            return new Promise((resolve, reject) => {
                if (this.ws && this.ws.readyState === 1) {
                    console.log('内部消息已发送：');
                    this.ws.send(
                        JSON.stringify({
                            event: type,
                            data: data,
                            to: to
                        })
                    );
                    resolve({ type, data, to });
                } else {
                    console.warn('WebSocket连接尚未建立，无法发送消息', type, data, to);
                    reject();
                }
            });
        },
		startDraw() {
			this.canvas = new fabric.Canvas("canvas", {
				isDrawingMode: false, //设置是否可以绘制
				selectable: false, //设置是否可以选中拖动  fabric提供的
				selection: false,
				skipTargetFind: true, //画板元素不能被选中
				selectionFullyContained: true, // 只选择完全包含在拖动选择矩形中的形状
				backgroundColor: "rgba(0,0,0,0)", // 画布背景色
			});
			// 鼠标按下
			this.canvas.on("mouse:down", (options) => {
				console.log("鼠标按下", options);
				this.doDrawing = true;
				this.currentObjectAid = Date.now();
				// 鼠标按下时记录下起点的xy坐标
				this.mouseFrom = { ...options.absolutePointer };
				this.drawing(); //执行绘制方法
			});
			// 鼠标移动
			this.canvas.on("mouse:move", (options) => {
				if (!this.doDrawing) return;
				console.log("鼠标移动:", options);
				// 鼠标移动时记录下终点的xy坐标
				this.mouseTo = { ...options.absolutePointer };
				if (
					this.mouseTo.x == this.mouseFrom.x &&
					this.mouseTo.y == this.mouseFrom.y
				)
					return;
				// 鼠标移动元素
				this.moveCanvasObject();
			});
			// 鼠标抬起
			this.canvas.on("mouse:up", (options) => {
				this.doDrawing = false;
				console.log("抬起", options, this.canvas.getObjects().pop());
				this.drawingObject = null;

				this.mouseTo = { ...options.absolutePointer };
			});
		},
		stopDraw() {

        },
		drawing(channelData) {
			this.drawLine((call) => {
				console.log("😱 ~ this.drawLine ~ call:", call, call.pathData.aID);
				if (!call.pathData.aID) {
					call.pathData.aID = this.currentObjectAid;
				}
				this.canvasObjectAdd(call.pathData, call.canvasObject, channelData);
			}, channelData);
		},
		// 绘制直线
		drawLine(callback, channelData) {
			let pathData = {};
			if (channelData) {
				pathData = channelData;
			} else {
				// 1.有圆角
				// 根据保存的鼠标起始点坐标 创建直线对象
				let x1 = this.getTransformedPosX(this.mouseFrom.x),
                    y1 = this.getTransformedPosY(this.mouseFrom.y)
				console.log("绘制直线", x1, y1);
				let path = "M " + x1 + " " + y1;
				path += " L " + x1 + " " + y1;
				path += " Z";

				pathData = {
					path,
					canvasObjectDefault: this.canvasObjectDefault,
				};
			}

			let canvasObject = new fabric.Path(pathData.path, {
				...pathData.canvasObjectDefault, // 公共绘制参数
			});
			callback({ pathData, canvasObject });
		},
		// 将图形添加到画布上公共方法
		canvasObjectAdd(obj, canvasObject, isChannel) {
			// 防止出现好多个
			if (canvasObject) {
				// console.log('canvasObjectcanvasObject',canvasObject);
				canvasObject.set("aID", obj.aID);
				this.canvas.add(canvasObject);
				this.canvas.renderAll();

				this.drawingObject = canvasObject;
				console.log(
					"😱 ~ canvasObjectAdd ~ canvasObject:",
					obj,
					this.drawingObject,
					isChannel
				);

				// 数据通道同步绘制画板
				if (isChannel) return;
                this.send({type:"line",canvasObject: obj})
			}
		},
		// 鼠标移动元素
		moveCanvasObject() {
			let canvasObject = {
				aID: this.currentObjectAid,
			};
			let x1 = this.getTransformedPosX(this.mouseFrom.x),
                x2 = this.getTransformedPosX(this.mouseTo.x),
                y1 = this.getTransformedPosY(this.mouseFrom.y),
                y2 = this.getTransformedPosY(this.mouseTo.y);
			let path = "M " + x1 + " " + y1;
			path += " L " + x2 + " " + y2;
			path += " Z";
			canvasObject = Object.assign(canvasObject, { path });
			console.log("linelinelineline", canvasObject);
			this.setCanvasObject(canvasObject);
			this.send({type:"canvasMove",canvasObject: canvasObject})
		},
		// 更新元素属性
		setCanvasObject(data) {
            console.log("更新元素属性",data,this.canvas.getObjects());
			this.canvas.forEachObject((object) => {
				if (object.aID == data.aID) {
					// 图形
					if (!data.path && !data.points) {
						object.set(data);
					}
					// 路径
					if (data.path) {
						// 创建新的Path对象
						let newPath = new fabric.Path(data.path);
						let newPathObj = {};
						Object.keys(newPath).map((item, index) => {
							newPathObj[item] = newPath[item];
						});
						object.setOptions(newPathObj);
					}
					// 多边形
					if (data.points) {
						// 创建新的Path对象
						let newPath = new fabric.Polygon(data.points);
						let newPathObj = {};
						Object.keys(newPath).map((item, index) => {
							newPathObj[item] = newPath[item];
						});
						object.setOptions(newPathObj);
					}
					object.setCoords();
				}
			});
			this.canvas.requestRenderAll();
		},

        // 清空画板
        clear(){
            this.canvas.discardActiveObject();
            this.canvas.clear();
            this.canvas.requestRenderAll();
        },
        getTransformedPosX(x) {
            let zoom = Number(this.canvas.getZoom())
            return (x - this.canvas.viewportTransform[4]) / zoom;
        },
        getTransformedPosY(y) {
            let zoom = Number(this.canvas.getZoom())
            return (y - this.canvas.viewportTransform[5]) / zoom;
        },

        // 发送单条消息
        chatSend(){
            let data = {
                type: "msg",
                chatVal: this.chatVal,
                userId: this.value
            }
            this.send(data)
        }

	},
    beforeDestroy() {
        this.stopConnect()
    }
};
</script>

<style scoped>
.draw {

}
#canvas{
border: 1px solid #000;
}
</style>
